﻿using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text;

namespace DimensionsHelper.LanguageService.Syntax;

[DebuggerDisplay("{ToDisplayString(),nq}")]
public class MacroExpansion : PreNodeList
{
    private readonly SourceNode _sourceExpression;

    internal MacroExpansion(SourceNode? parent, SourceNode source) :
        base(parent, SyntaxKinds.MacroExpansion)
    {
        SetFlags(source.GetFlags());
        SetChildField(ref _sourceExpression, source);
    }


    /// <summary>
    ///     空展开列表
    /// </summary>
    internal static MacroExpansion Empty => new(null, Default);


    /// <summary>
    ///     宏扩展的原始节点
    /// </summary>
    public SourceNode Source => _sourceExpression;

    public override string Text => ToDisplayString();


    public override int Start => Source.Start;

    public override int End => Source.End;

    public override int Width => Source.Width;

    public override TextSpan Span => Source.Span;


    /// <summary>
    ///     如果当前宏展开通过多步骤展开得到，此属性为第一步的展开结果。
    /// </summary>
    public MacroExpansion? ExpansionByStep { get; internal set; }


    /// <summary>
    ///     是否包含嵌套宏
    /// </summary>
    public bool IsNested { get; private set; }


    public static bool IsEmptyExpansion([NotNullWhen(false)] MacroExpansion? expansion)
    {
        return expansion == null
               || ReferenceEquals(expansion, Empty)
               || expansion.NodeListInternal.IsEmpty;
    }


    public override void AddNode(SourceNode node)
    {
        if (node.IsMacroExpansion)
        {
            if (IsEmptyExpansion((MacroExpansion)node))
            {
                return;
            }

            IsNested = true;
        }

        base.AddNode(node);
    }


    public override string ToDisplayString()
    {
        StringBuilder sb = new();

        SourceNode? last = null;
        foreach (SourceNode node in NodeListInternal)
        {
            if (last == null)
            {
                last = node;
            }
            else
            {
                if (node.Span.Start - last.Span.End > 0)
                {
                    sb.Append(' ');
                }
            }

            sb.Append(node.Text);
        }

        return sb.ToString();
    }
}


public static partial class NodeFactory
{
    public static MacroExpansion CreateMacroExpansion(SourceNode? parent, SourceNode source)
    {
        return new MacroExpansion(parent, source);
    }
}